import { DownOutlined } from '@ant-design/icons';
import { useSize } from 'ahooks';
import { Col, ColProps, Row, RowProps } from 'antd';
import { ReactElement, ReactNode, useMemo, useRef, useState } from 'react';
import { BreakPointType, getBreakPoint, getSpanFromPoint } from './breakpoint';

/**
 * @desc 根据当前断点及断点配置生成对应的col配置
 */
function parseColPropsFromPointType(
  colProps: ColProps,
  pointType: BreakPointType,
): Omit<ColProps, BreakPointType> {
  const { xs, xl, xxl, sm, lg, md, ...rest } = colProps;
  const responsive = { xs, xl, xxl, sm, lg, md };
  const config = responsive[pointType];
  let parseInfo: Omit<ColProps, BreakPointType> = {
    span: colProps.span,
    ...rest,
  };
  if (typeof config === 'number' || typeof config === 'string') {
    parseInfo.span = config;
  } else if (typeof config === 'object') {
    Object.assign(parseInfo, config);
  }
  return parseInfo;
}

/**
 * @desc 根据colProps的参数解析当前 Col 组件的实际生效span值
 */
function parseSpanFromColProps(colProps: ColProps, pointType: BreakPointType) {
  let span = colProps[pointType] ?? colProps['span'];
  let n: number | undefined;
  if (typeof span === 'number' || typeof span === 'string') {
    n = Number(span);
  } else if (typeof span === 'object') {
    if (span.span || span.offset) {
      n = Number(Number(span.span ?? 0) + Number(span.offset ?? 0));
    }
  }
  return n;
}

export interface ItemLayoutPorps extends Omit<RowProps, 'children'> {
  /**
   * @desc 给所有的span配置默认值
   */
  span?: number | Record<BreakPointType, number>;

  items?: ColProps[];
  /**
   * @desc 特殊col的icon插槽
   */
  extraRender?: (info?: {
    collapsedIcon: ReactElement | null;
    collapsed: boolean;
    setCollapsed(collapsed: boolean): void;
  }) => ReactNode;
  /**
   * @desc 特殊col的props配置
   */
  extraColProps?: ColProps;

  collapsed?: boolean;
  /**
   * @desc 默认是关闭的
   */
  defaultCollapsed?: boolean;

  onCollapsed?(collapsed: boolean): void;
}

export function ItemLayout({
  span,
  items,
  extraRender,
  defaultCollapsed,
  extraColProps,
  collapsed: invokeCollapsed,
  onCollapsed,
  ...rowProps
}: ItemLayoutPorps) {
  const wrapperDom = useRef<HTMLDivElement>(null);
  const size = useSize(wrapperDom);
  const [insideCollapsed, setCollapsed] = useState(() => {
    return invokeCollapsed ?? defaultCollapsed ?? false;
  });

  // 判断是否折叠
  const collapsed = useMemo(() => {
    return invokeCollapsed ?? insideCollapsed;
  }, [insideCollapsed, invokeCollapsed]);

  const changeCollapsed = (collapsed: boolean) => {
    setCollapsed(collapsed);
    onCollapsed?.(collapsed);
  };

  // 计算得到当前元素断点值，当前断点下的默认span值
  const { pointType, colSpan } = useMemo(() => {
    const pointType = getBreakPoint(size?.width ?? 0);

    let realSpan: number | undefined;
    if (typeof span === 'number') {
      realSpan = span;
    } else if (typeof span === 'object') {
      realSpan = span[pointType];
    }
    const colSpan = realSpan ?? getSpanFromPoint(pointType);
    return {
      pointType,
      colSpan,
    };
  }, [size?.width, span]);

  // 获取额外的col的透传props
  const extraExtendsPorps = useMemo(() => {
    const npResProps = parseColPropsFromPointType(
      extraColProps ?? {},
      pointType,
    );
    npResProps.span ??= colSpan;
    return npResProps;
  }, [pointType, colSpan, extraColProps]);

  // 获取额外col的span值
  const extraColSpan = Number(extraExtendsPorps.span);

  // 计算是否需要折叠按钮
  const needCollapsedIcon = useMemo(() => {
    // 计算是否需要展开按钮
    const total =
      items?.reduce((a, colProps) => {
        let n = parseSpanFromColProps(colProps, pointType) ?? colSpan;
        return a + n;
      }, 0) ?? 0;

    return total + extraColSpan > 24;
  }, [items, colSpan, pointType, extraColSpan]);

  // 渲染cols的列表
  const renderItems = useMemo(() => {
    // 计数，并且考虑隐藏
    let total = 0;

    return items?.map((colProps) => {
      const noResColProps = parseColPropsFromPointType(colProps, pointType);
      noResColProps.span ??= colSpan;

      total += Number(noResColProps.span);
      let hidden = false;
      if (collapsed === true && total > 24 - extraColSpan) {
        hidden = true;
      }

      return {
        hidden,
        ...noResColProps,
      };
    });
  }, [items, pointType, colSpan, collapsed]);

  // 给 extraRender 的参数
  const info = needCollapsedIcon
    ? {
        collapsedIcon: (
          <DownOutlined
            onClick={() => changeCollapsed(!collapsed)}
            style={{
              transition: '.3s all',
              transform: `rotate(${collapsed ? 0 : 0.5}turn)`,
            }}
          />
        ),
        collapsed,
        setCollapsed: changeCollapsed,
      }
    : undefined;

  return (
    <Row gutter={[24, 24]} ref={wrapperDom} wrap {...rowProps}>
      {renderItems?.map(({ ...props }, index) => {
        return <Col {...props} key={index} />;
      })}
      <Col span={extraColSpan} {...extraColProps}>
        {extraRender?.(info)}
      </Col>
    </Row>
  );
}
